/**********************************************************************
* Filename: Equipa.java
* Created: 2012/04/30
* @author Fernando Brito e Abreu
**********************************************************************/
package pt.iscteiul.worldfootball.businesslayer;

import java.util.Set;
import java.util.HashSet;

import com.projectpoint.annotationnotfinished.NotFinished;
@NotFinished(value="Not tested")
public class Equipa implements Cloneable
{
	public static Set<Equipa> allInstances = new HashSet<Equipa>();
	
	private Jogo jogo;
	private Pais seleccao;
	
	private Equipa OLD;
	
	@Override
	protected Object clone() throws CloneNotSupportedException {
		Equipa equipa = new Equipa((Jogo)jogo.clone(), (Pais)seleccao.clone());
		Equipa.allInstances.remove(equipa);
		return equipa;
	}
	/**********************************************************************
	* Default constructor
	**********************************************************************/
	public Equipa()
	{
		allInstances.add(this);
	}
	
	/**********************************************************************
	* Parameterized constructor
	* @param jogo the jogo to initialize
	* @param seleccao the seleccao to initialize
	**********************************************************************/
	public Equipa(Jogo jogo, Pais seleccao)
	{
		this.jogo = jogo;
		this.seleccao = seleccao;
		allInstances.add(this);
	}
	
	/**********************************************************************
	* ASSOCIATIVE2MEMBER getter for Equipa[*] <-> Jogo[1]
	* @return the jogo of the equipa
	**********************************************************************/
	public Jogo jogo()
	{
		return jogo;
	}
	
	/**********************************************************************
	* ASSOCIATIVE2MEMBER setter for Equipa[*] <-> Jogo[1]
	* @param jogo the jogo to set
	**********************************************************************/
	public void setJogo(Jogo jogo)
	{
		this.jogo = jogo;
	}
	
	/**********************************************************************
	* ASSOCIATIVE2MEMBER getter for Equipa[*] <-> Pais[1]
	* @return the seleccao of the equipa
	**********************************************************************/
	public Pais seleccao()
	{
		return seleccao;
	}
	
	/**********************************************************************
	* ASSOCIATIVE2MEMBER setter for Equipa[*] <-> Pais[1]
	* @param seleccao the seleccao to set
	**********************************************************************/
	public void setSeleccao(Pais seleccao)
	{
		this.seleccao = seleccao;
	}
	
	/**********************************************************************
	* MEMBER2ASSOCIATIVE getter for Equipa[*] <-> Membro[11..*]
	* @return the membro of the equipa
	**********************************************************************/
	public Set<Membro> membro()
	{
		Set<Membro> result = new HashSet<Membro>();
		for (Membro x : Membro.allInstances)
			if (x.equipa()  ==  this)
				result.add(x);
		return result;
	}
	
	/**********************************************************************
	* MEMBER2ASSOCIATIVE setter for Equipa[*] <-> Membro[11..*]
	* @param membro the membro to set
	**********************************************************************/
	public void setMembro(Set<Membro> membro)
	{
		for (Membro x : membro)
			x.setEquipa(this);
	}
	
	/**********************************************************************
	* MEMBER2MEMBER getter for Equipa[*] <-> Jogador[11..*]
	* @return the jogador of the equipa
	**********************************************************************/
	public Set<Jogador> jogador()
	{
		Set<Jogador> result = new HashSet<Jogador>();
		for (Membro x : Membro.allInstances)
			if (x.equipa()  ==  this)
				result.add(x.jogador());
		return result;
	}
	
	/**********************************************************************
	* MEMBER2MEMBER setter for Equipa[*] <-> Jogador[11..*]
	* @param jogador the jogador to set
	**********************************************************************/
	public void setJogador(Set<Jogador> jogador)
	{
		for (Jogador t : jogador)
			for (Membro x: Membro.allInstances)
				if (x.equipa() == this)
					x.setJogador(t);
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	**********************************************************************/
	public void criaFichaJogoFalsa()
	{
		//	TODO
		//	jogadores := self.seleccao.participacao
		//	->select(p : Participacao | (p.participado = self.jogo.grupo.campeonato))
		//	->collectNested($e : Participacao | $e.plantel)
		//	->flatten->asSet;
		HashSet<Jogador> jogadores = new HashSet<Jogador>();
		for(Participacao p:this.seleccao.participacao()){
			if(p.participado().equals(this.jogo.grupo().campeonato())){
				for(Jogador j : p.plantel()){
					jogadores.add(j);
				}
			}
		}
		//	 for j in jogadores do 
		for(Jogador j: jogadores){
			//	membro := new Membro between (j,self);
			Membro membro = new Membro();
			membro.setJogador(j);
			membro.setEquipa(this);
			
			//	if (j.data_nascimento.isLeap() and ((j.data_nascimento.month = 3) or (j.data_nascimento.month = 9))) then 
			if(j.data_nascimento().isLeap() && (j.data_nascimento().month()==3 || j.data_nascimento().month() == 9)){
				//	 	cartaoA := new Cartao;
				Cartao cartaoA = new Cartao();
				//	 cartaoA.inicializa(TipoCartao::Amarelo, (j.data_nascimento.day + j.data_nascimento.month));
				cartaoA.inicializa(TipoCartao.Amarelo, (j.data_nascimento().day() + j.data_nascimento().month()));
				//	 insert (membro,cartaoA) into Membro_Cartao end;
				cartaoA.setMembro(membro);
			}
			
			//	 if ((j.data_nascimento.isLeap() and (j.data_nascimento.month = 3)) and (j.data_nascimento.day > 15)) then 
			if((j.data_nascimento().isLeap() && j.data_nascimento().month() ==3) && j.data_nascimento().day()>15){
				//	 cartaoV := new Cartao;
				Cartao cartaoV = new Cartao();
				//	 cartaoV.inicializa(TipoCartao::Vermelho, ((j.data_nascimento.day * 2) + j.data_nascimento.month));
				cartaoV.inicializa(TipoCartao.Vermelho, ((j.data_nascimento().day() * 2) + j.data_nascimento().month()));
				//	 insert (membro,cartaoV) into Membro_Cartao end;
				cartaoV.setMembro(membro);
			}
//			if (((j.data_nascimento.month > 7) and (j.data_nascimento.day < 15)) and (j.posicao = PosicaoJogador::Avancado)) then
			if(((j.data_nascimento().month() > 7) && (j.data_nascimento().day() < 15)) && (j.posicao().equals(PosicaoJogador.Avancado))){ 
				//	 golo := new Golo;
				Golo golo = new Golo();
				//	 golo.inicializa(if j.data_nascimento.isLeap() then (j.data_nascimento.month * 7) else j.data_nascimento.day endif);
				golo.inicializa(j.data_nascimento().isLeap()?(j.data_nascimento().month() * 7):j.data_nascimento().day());
				//	 insert (membro,golo) into Membro_Golo end
				golo.setMarcador(membro);
			}
		//	end;
		}
		

		
		
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	* @param pais the pais to set
	* @param jogo the jogo to set
	* @param jogadores the jogadores to set
	**********************************************************************/
	public void novaEquipa(Pais pais, Jogo jogo, Set<Jogador> jogadores)
	{
		//	TODO
		//	equipa := self;
		Equipa equipa = this;
		//	 if jogo.seleccao->exists(s : Pais | (s = pais)) then 
		// 	 	for jogador in self.jogador do 
		//			delete (jogador,self) from Membro 
		//		end 
		//	 else 
		//		equipa := new Equipa between (pais,jogo) 
		//	 end;
		boolean exists = false;
		for(Pais s:jogo.seleccao()){
			if(s.equals(pais)){
				exists=true;
				for(Jogador jogador:this.jogador()){
					//Delete player
					for(Membro membro:this.membro()){
						if(membro.jogador().equals(jogador)){
							Membro.allInstances.remove(membro);
						}
					}
					
				}
			}
		}
		if(!exists){
			equipa = new Equipa(jogo, pais);
		}
		
		//	 for jogador in jogadores do new Membro between (jogador,self) end;
		
		for(Jogador jogador: jogadores){
			Membro membro = new Membro();
			membro.setJogador(jogador);
			membro.setEquipa(this);
		}
		
	}
	
	protected boolean novaEquipa_Precondition(Pais pais, Jogo jogo, Set<Jogador> jogadores){
		//jogadores.iterate(j;res:Integer=0|res+1)<=11
		boolean contagemDeJogadoresCorrecta = jogadores.size()<=11;
		return contagemDeJogadoresCorrecta;
	}
	
	protected boolean novaEquipa_Postcondition(Pais pais, Jogo jogo, Set<Jogador> jogadores, Void RETURN){
		//self.jogador = jogadores
		boolean contagemDeJogadoresColocadosCorrecta = this.jogador().equals(jogadores);
		return contagemDeJogadoresColocadosCorrecta;
	}
	/* (non-Javadoc)
	* @see java.lang.Object#toString()
	*/
	@Override
	/**********************************************************************
	* Object serializer
	**********************************************************************/
	public String toString()
	{
		return "Equipa [jogo=" + jogo + ", seleccao=" + seleccao + "]\n";
	}
	
}
